#include "skynet.h"

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>

struct logger {
	FILE * handle;
	char * filename;
	int close;
};

static int nextcheck = 0;
static int fileindex = 1;
struct logger *
logger_create(void) {
	struct logger * inst = skynet_malloc(sizeof(*inst));
	inst->handle = NULL;
	inst->close = 0;
	inst->filename = NULL;

	return inst;
}

void
logger_release(struct logger * inst) {
	if (inst->close) {
		fclose(inst->handle);
	}
	skynet_free(inst->filename);
	skynet_free(inst);
}

void
logger_checkFileHull(struct logger * inst) {
	struct stat statbuf;  
	int size = 0;
	int ret = 0;
	if (++nextcheck < 200)
		return;
	nextcheck = 0;

	char path[512]; path[0] = '\0';
	if (fileindex > 1){
		sprintf(path,"%s_%d",inst->filename, (fileindex-1));
		ret = stat(path,&statbuf);  
	}else{
		ret = stat(inst->filename, &statbuf);  
	} 

	// find file no exits
	if (ret < 0){
		sprintf(path,"%s_%d",inst->filename,fileindex++);
		inst->handle = fopen(path,"w");
		return;
	}
    
    size = statbuf.st_size;  
	if (size > (1024*1024*100)){
		fclose(inst->handle);
		sprintf(path,"%s_%d",inst->filename,fileindex++);
		inst->handle = fopen(path,"w");
	}
}

static int
logger_cb(struct skynet_context * context, void *ud, int type, int session, uint32_t source, const void * msg, size_t sz) {
	struct logger * inst = ud;
	switch (type) {
	case PTYPE_SYSTEM:
		if (inst->filename) {
			char path[512]; path[0] = '\0';
			sprintf(path,"%s_%d",inst->filename,fileindex);
			inst->handle = freopen(path, "a", inst->handle);
		}
		break;
	case PTYPE_TEXT:
		{
		time_t timep; struct tm *p;  time(&timep); p=localtime(&timep);
		fprintf(inst->handle, "[%02d%02d%02d%02d%02d:%08x] ", (1+p->tm_mon),(p->tm_mday),(p->tm_hour),(p->tm_min),(p->tm_sec),source);
		fwrite(msg, sz , 1, inst->handle);
		fprintf(inst->handle, "\n");
		fflush(inst->handle);
		logger_checkFileHull(inst);
		}
		break;
	}

	return 0;
}

int
logger_init(struct logger * inst, struct skynet_context *ctx, const char * parm) {
	if (parm) {
		inst->handle = fopen(parm,"w");
		if (inst->handle == NULL) {
			return 1;
		}
		inst->filename = skynet_malloc(strlen(parm)+10);
		strcpy(inst->filename, parm);
		inst->close = 1;
	} else {
		inst->handle = stdout;
	}
	if (inst->handle) {
		skynet_callback(ctx, inst, logger_cb);
		skynet_command(ctx, "REG", ".logger");
		return 0;
	}
	return 1;
}
